package org.rency.ues.common;

import org.apache.commons.lang.StringUtils;
import org.rency.common.utils.security.DESUtils;
import org.rency.common.utils.security.X509CertUtils;
import org.rency.common.utils.validate.RegValidator;
import org.rency.ues.common.enums.EncryptType;
import org.rency.ues.common.model.EncryptData;
import org.springframework.util.Assert;

import java.lang.reflect.InvocationTargetException;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class UesUtils {

	private static final String defaultReplacement = "*"; // 掩码
	private static final String emailReplacement = "******"; // 掩码
	
	/**
	 * 获取掩码
	 * </br>Created on 2016年7月22日
	 * @param name
	 * @param summaryRule
	 * @param data
	 * @return
	 */
	public static String getSummary(String name, String summaryRule, String data) {
        if (StringUtils.isNotBlank(summaryRule)) {
            if (RegValidator.isEmail(data)) {
                return UesUtils.getEmailMask(data, summaryRule);
            } else {
                return UesUtils.getFiledMask(data, summaryRule);
            }
        }
        return null;
    }
	
	/**
     * 根据正则表达式计算得到掩码
     * @param filedValue 明文
     * @param regex		 表达式	
     * @return
     */
    public static String getFiledMask(String filedValue, String regex) {
        if (StringUtils.isBlank(filedValue)) {
            return null;
        }
        if (StringUtils.isBlank(regex)) {
            return filedValue;
        }
        Pattern p = Pattern.compile(regex); // 正则表达式
        Matcher m = p.matcher(filedValue); // 操作的字符串
        if (m.find()) {
            filedValue = getMatcherMask(m, filedValue, null);
        }
        return filedValue;
    }
    
    /**
     * 替换匹配的值为传入的值
     * @param m
     * @param filedValue
     * @param defaultReplaceValue
     * @return
     */
    private static String getMatcherMask(Matcher m, String filedValue, String defaultReplaceValue) {
        StringBuffer sf = new StringBuffer();

        for (int i = 1; i <= m.groupCount(); i++) {
            if (StringUtils.isBlank(defaultReplaceValue)) {
                defaultReplaceValue = getReplacement(m.group(i).length(), defaultReplacement);
            }
            if (m.start(i) == 0) {
                sf.append(defaultReplaceValue);
                if (filedValue.length() > m.end(i)) {
                    sf.append(filedValue.substring(m.end(i), filedValue.length()));
                }
            } else {
                sf.append(filedValue.substring(0, m.start(i)));
                sf.append(defaultReplaceValue);
                if (filedValue.length() > m.end(i)) {
                    sf.append(filedValue.substring(m.end(i), filedValue.length()));
                }
            }
            if (null != sf && sf.length() > 0) {
                filedValue = sf.toString();
            }
        }
        return filedValue;
    }
    
    public static String getReplacement(int length, String replacement) {
        StringBuffer sf = new StringBuffer();
        for (int i = 0; i < length; i++) {
            sf.append(replacement);
        }
        return sf.toString();
    }
	
    public static String getEmailMask(String email, String regex) {
        if (StringUtils.isBlank(email)) {
            return null;
        }
        if (StringUtils.isBlank(regex)) {
            return email;
        }
        Pattern p = Pattern.compile(regex); // 正则表达式
        Matcher m = p.matcher(email); // 操作的字符串
        if (m.find()) {
            // email = email.replace(m.group(i), emailReplacement);
            email = getMatcherMask(m, email, emailReplacement);
        } else {
            p = Pattern.compile("@"); // 正则表达式
            m = p.matcher(email); // 操作的字符串
            StringBuffer sf = new StringBuffer();
            if (m.find()) {
                if (m.start() == 1) {
                    sf.append(emailReplacement);
                    sf.append(email.substring(m.end() - 1, email.length()));
                }
                if (m.start() == 2) {
                    sf.append(email.substring(0, 1));
                    sf.append(emailReplacement);
                    sf.append(email.substring(m.end() - 2, email.length()));

                }
            }
            if (null != sf && sf.length() > 0) {
                email = sf.toString();
            }
        }
        return email;
    }
    
    /**
     * 计算摘要
     * </br>Created on 2016年7月28日
     * @param plainData
     * @param summaryStartIndex
     * @param summaryLength
     * @return
     * @throws IllegalArgumentException
     * @throws Exception
     */
    public static String caculateSummary(String plainData, int summaryStartIndex, int summaryLength) throws IllegalArgumentException, Exception {
        boolean validate = Math.abs(summaryStartIndex) < plainData.length();
        if (validate) {
            validate = Math.abs(summaryLength) <= plainData.length() / 2;
        }
        if (validate) {
            validate = (12 + Math.abs(summaryLength)) <= 32;
        }
        if (validate) {
            if (summaryStartIndex == 0) {
                validate = Math.abs(summaryStartIndex + summaryLength) <= plainData.length();
            } else if (summaryStartIndex > 0 && summaryLength >= 0) {
                validate = summaryStartIndex + summaryLength <= plainData.length();
            } else if (summaryStartIndex > 0 && summaryLength < 0) {
                validate = summaryStartIndex + 1 + summaryLength >= 0;
            } else if (summaryStartIndex < 0 && summaryLength >= 0) {
                validate = summaryStartIndex - 1 + summaryLength <= 0;
            } else if (summaryStartIndex < 0 && summaryLength < 0) {
                validate = Math.abs(summaryStartIndex + summaryLength) <= plainData.length();
            } else {
                validate = false;
            }
        }
        Assert.isTrue(validate, "Invalid summary information.summaryStartIndex[" + summaryStartIndex + "], summaryLength[" + summaryLength + "] ,plain data length[" + plainData.length() + "]");
        int start = 0;
        int end = 0;
        if (summaryStartIndex == 0) {
            if (summaryLength >= 0) {
                start = 0;
                end = summaryLength;
            } else if (summaryLength < 0) {
                start = plainData.length() + summaryLength;
                end = plainData.length();
            }
        } else if (summaryStartIndex > 0) {
            if (summaryLength >= 0) {
                start = summaryStartIndex;
                end = start + summaryLength;
            } else if (summaryLength < 0) {
                start = summaryStartIndex + 1 + summaryLength;
                end = summaryStartIndex + 1;
            }
        } else {
            if (summaryLength >= 0) {
                start = plainData.length() - 1 + summaryStartIndex;
                end = start + summaryLength;
            } else if (summaryLength < 0) {
                end = plainData.length() + summaryStartIndex;
                start = end + summaryLength;
            }
        }
        return StringUtils.substring(plainData,start,end).trim();
    }

    /**
     * 生成待加密数据
     * @param plainText
     * @param encryptType
     * @param x509
     * @return
     * @throws Exception
     */
    public static EncryptData generateEncryptData(String plainText, EncryptType encryptType, X509Certificate x509) throws Exception {
        EncryptData enData = new EncryptData();
        try{
            //生成随机密钥
            String randomKey = X509CertUtils.generateRandomKey(UesDict.DEFAULT_RANDOM_KEY_LENGTH);
            //根据随机密钥对数据加密
            String encryptedData = DESUtils.encryptDESede(plainText, randomKey);
            byte[] randomKeyBytes = randomKey.getBytes(UesDict.DEFAULT_CHARSET);
            //通过证书对随机密钥加密
            String encryptedKey;
            switch (encryptType) {
                case RSA:
                    encryptedKey = X509CertUtils.encryptRSA(randomKeyBytes, x509);
                    break;
                case CMS:
                    encryptedKey = X509CertUtils.encryptCMS(randomKeyBytes, x509);
                    break;
                default:
                    throw new InvocationTargetException(new Exception(String.format(UesDict.CHINESE_NOT_SUPPORT_ENCRYPT_TYPE_MSG,encryptType.getCode())));
            }
            enData.setSerialNo(x509.getSerialNumber().toString());
            enData.setEncryptedKey(encryptedKey);
            enData.setEncryptedData(encryptedData);
            enData.setEncryptType(encryptType);
        }catch (Exception e){
            throw e;
        }
        return enData;
    }

    public static String getPlainData(EncryptData enData, X509Certificate x509Certificate, PrivateKey privateKey) throws Exception {
        if(enData == null){
            return null;
        }
        EncryptType encryptType = enData.getEncryptType();
        byte[] resultKey = null;
        switch (encryptType) {
            case RSA:
                resultKey = X509CertUtils.decryptRSA(enData.getEncryptedKey(), privateKey);
                break;
            case CMS:
                resultKey = X509CertUtils.decryptCMS(enData.getEncryptedKey(), x509Certificate,privateKey);
                break;
            default:
                throw new InvocationTargetException(new Exception(String.format(UesDict.CHINESE_NOT_SUPPORT_ENCRYPT_TYPE_MSG,encryptType.getCode())));
        }
        if (resultKey == null) {
            throw new Exception(encryptType.getCode()+"密文解密失败,返回Bytes为空.");
        }
        String keyData = org.apache.commons.codec.binary.StringUtils.newStringUtf8(resultKey);
        return DESUtils.decryptDESede(enData.getEncryptedData(),keyData);
    }

}